#include "volume3D.h"
#include "octreeVolume.h"
#include <assert.h>
#include <stdio.h>

#include "nodePool3D.h"
#include "blockPool.h"


#define _DEBUG_MEMORY_LEAK

#ifdef _DEBUG_MEMORY_LEAK
	#define _CRTDBG_MAP_ALLOC
	#include <stdlib.h>
	#include <crtdbg.h>
#endif

#pragma comment(lib,"glew32.lib")
//stagbeetle-zyx-494X832X832.raw 832 832 494 1 beetleFR 1
int main(int argc, char *argv[])
{
	//delayed reading
	//volume3D *vol512 = new volume3D("head512X512X512.raw",512,512,512,1, true);
	//volume3D *vol129 = vol512->generateSubVolume(128,256,128,256,128,256); 
	//vol129->writeToFile("head_sub129X129X129.raw");
/*	volume3D *vol129 = new volume3D(129,129,129,1,255);
	//volume3D *voldown=vol256->generateDownSampleVolume();
	volume3D *voldown=vol256->generateDownSampleVolumeNN();
	//voldown->writeToFile("downSample128X128X128.raw");
	//voldown->writeToFile("NNdownSample128X128X128.raw");

	vol129->addSubVolume(voldown,0,0,0);
	//vol129->writeToFile("head129X129X129.raw");

	volume3D *sub = vol256->generateSubVolume(0,128,0,128,0,128);
	vol256->generateSubVolume(0,127,0,127,0,127)->writeToFile("test128.raw");
	//slice2D *slice = voldown->generateSliceX(64,0,64,0,64);
	//sub->writeToFile("sub129X129X129.raw");
	
	//slice->writeToFile("slice.raw");
	//sub->generateSliceX(128,0,128,0,128)->writeToFile("subslice129X129.raw");
	sub->updateSliceX(voldown->generateSliceX(64,0,64,0,64),128, 0,128,0,128);
	sub->updateSliceY(voldown->generateSliceY(64,0,64,0,64),128,0,128,0,128);
	sub->updateSliceZ(voldown->generateSliceZ(64,0,64,0,64),128,0,128,0,128);
	//sub->writeToFile("000_129X129X129.raw");

	volume3D *empty = new volume3D(129,129,129,1,0);
	volume3D *vol = new volume3D(258,258,258,1,255);
	//vol->addSubVolume(vol256->generateSubVolume(0,127,0,127,0,127),0,0,0);
	vol->addSubVolume(sub,0,0,0);
	vol->addSubVolume(vol129,129,129,129	);

	//vol->writeToFile("packtest258X258X258-Linear.raw");
	vol->writeToFile("packtest258X258X258-NN.raw");

	//vol->writeToFile("packtest258X258X258.raw");

	delete vol256;
	delete vol129;
	delete sub;

#ifdef _DEBUG_MEMORY_LEAK
	_CrtDumpMemoryLeaks();
#endif

	system("pause");*/

//	unsigned char v[8]={250,250,250,250, 0,0,0,0};
	//unsigned char v[8]={250, 0, 0, 0, 0,0,0,250};
	//volume3D *vol = new volume3D(v,2,2,2,1);
	//vol->writeToFile("test2X2X2.raw");
	//vol->generateUpSampleVolume()->generateUpSampleVolume()->generateUpSampleVolume()->writeToFile("test16x16x16.raw");

	//vol256->generateUpSampleVolume()->writeToFile("head512X512X512.raw");

	//delayed reading


	//volume3D *vol = new volume3D("stagbeetle832x832x494.raw", 494,832,832,2, false);
	//volume3D *vol_sub= new volume3D(512,512,512,2,0);
	//vol_sub->addSubVolume(vol->generateSubVolume(0,493,150,661,0,511),0,0,0);
	//vol_sub->generateVolume16bitTo8bit()->writeToFile("stagbeetle_sub512X512X512.raw");
	//volume3D *vol = new volume3D("stagbeetle_sub512X512X512.raw", 512,512,512,1);

	//octreeVolume *octreeVol = new octreeVolume(vol, 64);
	//octreeVol->generateBlockPoolGL();
	//octreeVol->generateNodePoolGL();


	//volume3D *vol = new volume3D("head256X256X256.raw", 256,256,256,1);
	//octreeVolume *octreeVol = new octreeVolume(vol, 64);

	//z y x dimension
	//volume3D *vol = new volume3D("stagbeetle832x832x494-8bit.raw",494,832,832,1);
	//octreeVolume *octreeVol = new octreeVolume(vol, 64);

	//volume3D *vol = new volume3D("head256X256X256.raw", 256,256,256,1);
	//vol->generateSubVolume(0,127,0,255,0,255)->writeToFile("head256X256X128.raw");

	//volume3D *vol = new volume3D("stagbeetle-zyx-494X832X832.raw", 494,832,832,1);
	//octreeVolume *octreeVol = new octreeVolume(vol, 32);

	//blockPool bP(octreeVol->getRoot(),32);
	//bP.generateBlockPacking();
	//bP.writeToFile("stagbeetleBlockPacking-32-boundary");
	//////bP.generateBlockPool();

	//nodePool3D nP(octreeVol->getRoot());
	//nP.debugOutput();
	//nP.writeToFile("stagbeetleblockPool3D-32");
	

	//test release
	//volume3D *vol = new volume3D("head256X256X256.raw", 256, 256, 256,1);
	//octreeVolume *octreeVol = new octreeVolume(vol, 32);

	//blockPool bP(octreeVol->getRoot(),32);
	//bP.generateBlockPacking();
	//bP.writeToFile("headBlockPacking-32-boundary");
	//////bP.generateBlockPool();

	//nodePool3D nP(octreeVol->getRoot());
	//nP.debugOutput();
	//nP.writeToFile("headnodePool3D-32");

	//1G
	if(argc<7)
	{
		printf("\n input filename, dimZ, dimY, dimX, elementByteSize, outputName, outputMode \n need more argument");
		exit(0);
	}
	int dimZ,dimY, dimX;
	dimZ = atoi(argv[2]);
	dimY = atoi(argv[3]);
   	dimX = atoi(argv[4]);
	int elementSize = atoi(argv[5]);
	int outputMode = atoi(argv[7]);
	
	volume3D *vol = new volume3D(argv[1], dimZ, dimY, dimX,elementSize);
	octreeVolume *octreeVol = new octreeVolume(vol, 32);
	delete(vol);

	blockPool bP(octreeVol->getRoot(),32);
	if(outputMode == 0)
		bP.generateBlockPacking();
	else if(outputMode == 1)
		bP.generateFullResolutionLevelBlockPool();
	bP.writeToFile(argv[6]);
	////bP.generateBlockPool();

	nodePool3D nP(octreeVol->getRoot());
	nP.debugOutput();
	nP.writeToFile(argv[6]);


#ifdef _NO_BOUNDARY
	octreeVol->writeBlockPoolToFile("headBlockPool-128-noboundary.raw");
	octreeVol->writeNodePoolToFile("headNodePool2D-128-noboundary.raw");
	//octreeVol->writeBlockPoolToFile("headBlockPool-64-noboundary.raw");
	//octreeVol->writeNodePoolToFile("headNodePool2D-64-noboundary.raw");

#else
	//octreeVol->writeBlockPoolToFile("headBlockPool-32-boundary.raw");
	//octreeVol->writeBlockPoolToFile("headBlockPool-16-boundary.raw");

	//octreeVol->writeBlockPoolToFile("headBlockPool-64-boundary.raw");
	//octreeVol->writeNodePoolToFile("headNodePool2D-64.raw");
	//octreeVol->write3DNodePoolToFile("headNodePool3D-64.raw");
	//octreeVol->writeBlockPoolToFile("headBlockPool-128-boundary.raw");
	//octreeVol->writeNodePoolToFile("headNodePool2D-128.raw");
#endif
	
	//nodePool3D nodePool(1);
	//nodeTexel node;
	//nodePool3D::setBlockNodeTexel(node, 1,3,2,1,1,2,3);
	//int subD, nz, ny, nx, bz, by, bx;
	//nodePool3D::getMaxSubDivision(node, subD);
	//nodePool3D::getNodePos(node, nz,ny,nx);
	//nodePool3D::getBlockPos(node, bz, by, bx);


	//delete octreeVol;
	return 0;
} 